package org.easyspec.domain

import org.easyspec.EasySpec
import org.easyspec.Context
import org.easyspec.Behavior
import org.easyspec.*

import groovy.xml.*

@EasySpec(interest='Html Report Generator')
class HtmlReportGenerator_when_processing_specifications_Test extends GroovyTestCase {
	String htmlString
	String outputFilePath
	Node html
	def testTime
	def testTitle
	def createdFileName

	@Context('when processing specifications')
	public void setUp() {
		def testFileSystem = { fileName, output ->
			htmlString = output
			outputFilePath = fileName
		    return true
		} as FileOutputHandler

		Calendar calendar = Calendar.getInstance()
		calendar.set(Calendar.YEAR, 2007)
		calendar.set(Calendar.MONTH, Calendar.OCTOBER)
		calendar.set(Calendar.DAY_OF_MONTH, 8)
		calendar.set(Calendar.HOUR, 10)
		calendar.set(Calendar.AM_PM, Calendar.AM)
		calendar.set(Calendar.MINUTE, 5)
		calendar.set(Calendar.SECOND, 4)
		testTime = calendar.getTime()
		def clockStub = [currentTime:{ return testTime }]

		def spec1 = new Specification(interest:'My Object', context:'when doing something interesting')
		spec1.addBehavior(new domain.Behavior(detail:'should do something', isImplemented:true))
		spec1.addBehavior(new domain.Behavior(detail:'should do something else', isImplemented:true))

		def spec2 = new Specification(interest:'My Fun Object', context:'when doing something interesting')
		spec2.addBehavior(new domain.Behavior(detail:'should do something fun', isImplemented:true))
		spec2.addBehavior(new domain.Behavior(detail:'should do something else fun', isImplemented:false))

		def specs = new Specifications()
		specs.add(spec1)
		specs.add(spec2)

		testTitle = 'Some Report Title'

		def generator = new HtmlReportGenerator(path:'test/path', fileSystem: testFileSystem, clock:clockStub)

		createdFileName = generator.generateReport(specs, testTitle)

		html = new XmlParser().parseText(htmlString)
	}

	@Behavior()
	public void test_should_send_html_output_to_a_file_named_index_in_the_specified_path() {
		assert outputFilePath == 'test/path/index.html'
	}

	@Behavior()
	public void test_should_set_the_root_node_to_HTML() {
		assert html.name() == 'html'
	}

	@Behavior()
	public void test_should_set_the_title_of_the_html_page() {
		assert html.head.title.text() == 'EasySpec Report'
	}

	@Behavior()
	public void test_should_generate_an_entry_for_each_specification() {
		assert html.body.table.size() == 2
		assertEquals('MyFunObjectwhendoingsomethinginteresting', html.body.table[0].'@id')
		assertEquals('MyObjectwhendoingsomethinginteresting', html.body.table[1].'@id')
	}

	@Behavior()
	public void test_should_set_table_style() {
		assert html.body.table.size() == 2
		assert html.body.table[0].'@class' == 'specTable'
		assert html.body.table[0].'@width' == '100%'

		assert html.body.table[1].'@class' == 'specTable'
		assert html.body.table[1].'@width' == '100%'
	}

	@Behavior()
	public void test_should_include_the_css_page() {
		def link = html.head.link[0]

		assert link.'@href' == 'http://easyspec.googlecode.com/svn/trunk/resources/css/styles.css'
		assert link.'@media' == "all"
		assert link.'@rel' == "Stylesheet"
		assert link.'@type' == "text/css"
	}


	@Behavior()
	public void test_should_include_the_interest_and_context_with_each_specification_entry() {
		assertEquals('My Fun Object, when doing something interesting', html.body.table[0].tr[0].td.span.text())
		assertEquals('My Object, when doing something interesting', html.body.table[1].tr[0].td.span.text())
	}

	@Behavior()
	public void test_should_report_individual_behaviors() {
		assertEquals('should do something fun', html.body.table[0].tr[1].td.span.text())
		assertEquals('should do something else fun', html.body.table[0].tr[2].td.span.text())

		assertEquals('should do something', html.body.table[1].tr[1].td.span.text())
		assertEquals('should do something else', html.body.table[1].tr[2].td.span.text())
	}

	@Behavior()
	public void test_should_style_implemented_behaviors() {
		assertEquals('implemented', html.body.table[0].tr[1].td[0].'@class')

		assertEquals('implemented', html.body.table[1].tr[1].td[0].'@class')
		assertEquals('implemented', html.body.table[1].tr[2].td[0].'@class')
	}

	@Behavior()
	public void test_should_style_unimplemented_behaviors_differently() {
		assertEquals('pending', html.body.table[0].tr[2].td[0].'@class')
	}

	@Behavior
	public void test_should_style_interest_and_context_based_on_whether_behaviors_are_implemented() {
		assertEquals('pendingSpec', html.body.table[0].tr[0].td[0].'@class')
		assertEquals('implementedSpec', html.body.table[1].tr[0].td[0].'@class')
	}

	@Behavior
	public void test_should_include_a_report_title() {
		assertEquals(testTitle, html.body.div[0].span.text())
		assertEquals('reportTitle', html.body.div[0].'@class')
	}

	@Behavior
	public void test_should_include_a_timeStamp() {
		assertEquals('2007-10-08 at 10:05:04', html.body.div[1].span.text())
		assertEquals('reportTime', html.body.div[1].'@class')
	}

	@Behavior
	public void test_should_indicate_the_name_of_the_file_that_was_created() {
		assertEquals('index.html', createdFileName)
	}
}